/* Copyright 2014 Jan Wolter */

/* A "Course" is the foundation/waste pile used in games like Golf and
 * TriPeaks. There is just one stack, you can deal cards to it, or you can
 * build up or down on it. Getting all cards in is a win.
 */

#include "stack.h"
#include "course.h"

/* Array of course piles used in this game */
CourseStack *course;
int coursesize= 0;       /* current size of course array */

int course_mayInsert(Stack *dst, Card *card, int len, Stack *src)
{
    if (len > 1) return 0;

    /* Any card can be played if the course is empty */
    if (dst->n == 0) return 1;

    CourseStack *f= course + dst->tid;

    int toppip= topStack(dst)->n;
    int newpip= card->n;

    if (toppip == 13)
	return ((newpip == 12 && f->mayqueen) || (newpip == 1 && f->maywrap));
    else if (toppip == 1)
	return (newpip == 2 || (newpip == 13 && f->maywrap));
    else
	return (newpip == toppip - 1 || newpip == toppip + 1);
}


void makeCourse(int maywrap, int mayqueen, Stack *deal)
{
    /* Make sure we have memory for another course pile */
    if (coursesize == 0)
    {
	coursesize= 1;
	course= (CourseStack *)malloc(coursesize*sizeof(CourseStack));
    }
    else if (ncourse == coursesize)
    {
	coursesize+= 1;
	course= (CourseStack *)realloc(course,coursesize*sizeof(CourseStack));
    }

    /* Create the course pile */
    course[ncourse].maywrap= maywrap;
    course[ncourse].mayqueen= mayqueen;

    /* It starts out with only one card on it, but we allocate enough memory
     * for it to hold a whole deck.
     */
    course[ncourse].id= newStack(COURSE,ncourse,ncard,
	course_mayInsert,NULL,NULL,NULL);

    /* Deal in one card */
    if (deal)
    {
	Card *c= popStack(deal);
	if (c != NULL)
	{
	    c->faceup= 1;
	    pushStack(stacks+course[ncourse].id, c);
	}
    }

    ncourse++;
}

void cleanCourse()
{
    free(course);
    ncourse= coursesize= 0;
}

void printCourse(FILE *f, Stack *stks)
{
    char label[8];
    for (int k= 0; k < ncourse; k++)
    {
	sprintf(label,"F%02d", k+1);
	printStack(f, label, stks+course[k].id);
    }
}

int nOff()
{
    int n= 0;
    for (int k= 0; k < ncourse; k++)
	n+= stacks[course[k].id].n;
    return n;
}

/* Remove cards from all course and append them to the given stack,
 * reversing them all. If empty is true, we empty the course, otherwise the
 * course is unaltered.
 */
void gatherCourse(Stack *s, int empty)
{
    for (int k= 0; k < ncourse; k++)
    {
	Stack *cs= stacks+course[k].id;
	appendStack(s, cs, 1);
	if (empty) cs->n= 0;
    }
}

int courseid(int i)
{
    return course[i].id;
}
